package org.orbis.search.xml.impl;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.dom.DOMSource;
import org.orbis.search.SearchResult;
import org.orbis.search.SearchResultPackage;
import org.orbis.search.xml.SearchResultXML;
import org.orbis.structure.ContentInfo;
import org.orbis.term.tool.StringConverter;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class SimpleXML implements SearchResultXML{
	@Override
	public DOMSource createXML(String query, int from, int length, boolean operator, SearchResultPackage pkg,
		ContentInfo contentInfo) throws ParserConfigurationException, TransformerConfigurationException{
		// parse output to structured language
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = builderFactory.newDocumentBuilder();
		DOMImplementation domimpl = builder.getDOMImplementation();
		Document rootDoc = domimpl.createDocument("", "results", null);
		Element root = rootDoc.getDocumentElement();

		Element queryElem = rootDoc.createElement("query");
		queryElem.appendChild(rootDoc.createTextNode(query));
		root.appendChild(queryElem);

		Element startElem = rootDoc.createElement("from");
		startElem.appendChild(rootDoc.createTextNode(Integer.toString(from)));
		root.appendChild(startElem);

		Element rowElem = rootDoc.createElement("length");
		rowElem.appendChild(rootDoc.createTextNode(Integer.toString(length)));
		root.appendChild(rowElem);

		Element operatorElem = rootDoc.createElement("operator");
		operatorElem.appendChild(rootDoc.createTextNode(operator? "AND": "OR"));
		root.appendChild(operatorElem);

		Element hitCountElem = rootDoc.createElement("total");
		hitCountElem.appendChild(rootDoc.createTextNode(Integer.toString(pkg.count())));
		root.appendChild(hitCountElem);

		for(SearchResult result: pkg){
			Element mainElem = rootDoc.createElement("result");

			Element indexElem = rootDoc.createElement("index");
			indexElem.appendChild(rootDoc.createTextNode(String.format("%d", result.index())));
			mainElem.appendChild(indexElem);

			Element IDElem = rootDoc.createElement("ID");
			IDElem.appendChild(rootDoc.createTextNode(Long.toString(result.internalID())));
			mainElem.appendChild(IDElem);

			// Content
			Element[] contentElems = new Element[contentInfo.contentsNum()];
			for(int i = 0; i < contentInfo.contentsNum(); i++){
				contentElems[i] = rootDoc.createElement(contentInfo.contentName(i));
				String showResult = StringConverter.convert(result.content(i));
				if(showResult == null) showResult = "";
				contentElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(contentElems[i]);
			}

			// Appendix
			Element[] appendixElems = new Element[contentInfo.appendixNum()];
			for(int i = 0; i < contentInfo.appendixNum(); i++){
				appendixElems[i] = rootDoc.createElement(contentInfo.appendixName(i));
				String showResult = StringConverter.convert(result.appendix(i));
				if(showResult == null) showResult = "";
				appendixElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(appendixElems[i]);
			}

			// Boolean flags
			Element[] boolFlagElems = new Element[contentInfo.binaryFlagNum()];
			for(int i = 0; i < contentInfo.binaryFlagNum(); i++){
				boolFlagElems[i] = rootDoc.createElement(contentInfo.binaryFlagName(i));
				String showResult = Boolean.toString(result.binaryFlags()[i]);
				boolFlagElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(boolFlagElems[i]);
			}

			// Integer flags
			Element[] intFlagElems = new Element[contentInfo.integerFlagNum()];
			for(int i = 0; i < contentInfo.integerFlagNum(); i++){
				intFlagElems[i] = rootDoc.createElement(contentInfo.integerFlagName(i));
				String showResult = Integer.toString(result.intFlags()[i]);
				intFlagElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(intFlagElems[i]);
			}

			// Long flags
			Element[] longFlagElems = new Element[contentInfo.longFlagNum()];
			for(int i = 0; i < contentInfo.binaryFlagNum(); i++){
				longFlagElems[i] = rootDoc.createElement(contentInfo.longFlagName(i));
				String showResult = Long.toString(result.longFlags()[i]);
				longFlagElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(longFlagElems[i]);
			}

			// Float flags
			Element[] floatFlagElems = new Element[contentInfo.floatFlagNum()];
			for(int i = 0; i < contentInfo.binaryFlagNum(); i++){
				floatFlagElems[i] = rootDoc.createElement(contentInfo.floatFlagName(i));
				String showResult = Float.toString(result.floatFlags()[i]);
				floatFlagElems[i].appendChild(rootDoc.createTextNode(showResult));
				mainElem.appendChild(floatFlagElems[i]);
			}

			Element scoreElem = rootDoc.createElement("rank");
			scoreElem.appendChild(rootDoc.createTextNode(Double.toString(result.score())));
			mainElem.appendChild(scoreElem);

			root.appendChild(mainElem);
		}

		DOMSource source = new DOMSource(root);
		return source;
	}
}
